source('../settings/settings.R')
source('commonFunctions.R')
persons <- SELECTED_SUBJECTS

all_Drive4 <- read.csv('../data/processed/distancewise/TT1_Drive_4_30m_30m.csv')
all_Drive4$Subject <- as.factor(all_Drive4$Subject)
all_Drive4$logPerspiration <- log(all_Drive4$Perspiration)

# starting_points = c( 669 , 668 , 676 , 687 , 680 ,  676 ,  678 ,
#                      693 , 722 , 723 , 677 , 679 ,  711 ,  707 ,  
#                      699 , 679 , 684 , 688 , 686 ,  696 ,  702 )
# 
# ending_points   = c( 741 , 786 , 749 , 782 , 736 ,  756 ,  768 ,  
#                      812 , 853 , 792 , 783 , 772 ,  799 ,  781 ,  
#                      777 , 763 , 795 , 791 , 832 ,  755 ,  758 )

peak_points     = c( 67 ,  86 ,  73 ,  73 ,  73 ,  64 ,  73 ,  
                     79 ,  69 ,  64 ,  68 ,  67 ,  77 ,  68 ,  
                     82 ,  67 ,  72 ,  72 ,  71 ,  68 ,  64 )

# Driving time
driving_times = vector(mode="list", length = length(persons))
names(driving_times) <- persons

activity_names = vector(mode="list", length = length(persons))
names(activity_names) <- persons

acc_start_times = vector(mode="list", length = length(persons))
names(acc_start_times) <- persons
acc_end_times = vector(mode="list", length = length(persons))
names(acc_end_times) <- persons

stressor_start_times = vector(mode="list", length = length(persons))
names(stressor_start_times) <- persons
stressor_end_times = vector(mode="list", length = length(persons))
names(stressor_end_times) <- persons

complete_times = vector(mode="list", length = length(persons))
names(complete_times) <- persons

data_baseline = vector(mode="list", length=length(persons))
pp_baseline = vector(mode="list", length=length(persons))

names(data_baseline) <- persons
names(pp_baseline) <- persons

# Number of peaks

PREV_DISTANCE = 300
TRACKING_DISTANCE = 60
DRIVE_MODE = 4
getActivityName <- function(x, fullname=F) {
  if(x == 1) return(ifelse(fullname, "Normal", "NO"))
  if(x == 2) return(ifelse(fullname, "Cognitive", "C"))
  if(x == 3) return(ifelse(fullname, "Motoric", "M"))
}

for (p in persons) {
  pData <- all_Drive4[all_Drive4$Subject==as.integer(p) | all_Drive4$Subject==p,]
  pAcc <- pData[pData$Failure>0.5,] # Failure = 1
  acc_start_times[[p]] <- min(pAcc$Distance)
  acc_end_times[[p]] <- max(pAcc$Distance)
  
  activity_names[[p]] <- getActivityName(pData[pData$Time==60,]$Activity, fullname = T)
  
  pStressor = pData[pData$Activity>1.5,] # Stressor = 2, 3
  if (nrow(pStressor) > 0) {
    stressor_start_times[[p]] <- min(pStressor$Distance)
    stressor_end_times[[p]] <- max(pStressor$Distance)
  } else {
    stressor_start_times[[p]] <- NULL
    stressor_end_times[[p]] <- NULL
  }
}
DELAY_DISTANCE <- 10

idx <- 1
plt_AllAcc <- vector(mode="list", length=length(persons)) 
names(plt_AllAcc) <- persons

COLOR_ACC = "#02A3C8"
COLOR_PP = "#F28E8E"
COLOR_BRAKE = "#888888"

y1 <- list(
  tickfont = list(color = COLOR_ACC),
  title="Degree",
  range=c(0, 100)
)
y2 <- list(
  tickfont = list(color = COLOR_PP),
  overlaying = "y",
  side = "right",
  title = "Log Perspiration",
  showgrid = FALSE,
  range=c(min(all_Drive4$ppLogNormalized), max(all_Drive4$ppLogNormalized))
)
  
for (p in persons) {
  pData <- all_Drive4[all_Drive4$Subject==as.integer(p) | all_Drive4$Subject==p,]
  
  # Baseline
  data_baseline[[p]] <- read.csv(str_interp("../data/processed/drives/T0${person}/T0${person}_Drive_1.csv", list(person=p)))
  # Compute the mean
  p_pp_nr <- data_baseline[[p]]$Perspiration
  p_pp_nr <- p_pp_nr[!is.na(p_pp_nr)]
  pp_baseline[[p]] <- log(mean(p_pp_nr))
  
  # Incident
  driving_times[[p]] <- max(pData$Distance)
  
  incident_starting_time <- acc_start_times[[p]] # starting_points[idx]
  incident_ending_time <- acc_end_times[[p]]
  complete_times[[p]] <- ifelse(incident_starting_time + TRACKING_DISTANCE > driving_times[[p]], driving_times[[p]], incident_starting_time + TRACKING_DISTANCE)
  
  from_time <- ifelse(incident_starting_time - PREV_DISTANCE >= 0, incident_starting_time - PREV_DISTANCE, 0)
  to_time <- complete_times[[p]]
  
  # print(paste("From", from_time))
  # print(paste("Incident", incident_starting_time))
  # print(paste("To", to_time))
  
    
  pDataBefore <- pData[pData$Distance < incident_starting_time & pData$Distance >= from_time,]
  pDataAfter <- pData[pData$Distance >= incident_starting_time + DELAY_DISTANCE & pData$Distance <= to_time,]
  
  # print(nrow(pDataBefore))
  # print(nrow(pDataAfter))
  
  ppMeanBefore <- mean(pDataBefore$ppLogNormalized)
  ppMeanAfter <- mean(pDataAfter$ppLogNormalized)
  
  dir.create(file.path('../figures/drive/', paste0('Drive_', DRIVE_MODE)), showWarnings = FALSE)
  fname <- str_interp('../figures/drive/Drive_${drive}/P${person}.svg', list(drive=DRIVE_MODE, person=p)) 
  
  pData <- pData[pData$Distance >= from_time,]
  plot_Acc <- plot_ly(pData, x = ~Distance, height=400, width=900) %>%
              add_trace(name="Acceleration", y = ~Acceleration, type = 'scatter', mode = 'lines', line=list(width=1.5, color=COLOR_ACC)) %>% 
              add_trace(name="Brake", y = ~Braking, type = 'scatter', mode = 'lines', line=list(width=1.5, color=COLOR_BRAKE)) %>%
              add_trace(name="PP", y = ~ppLogNormalized, type = 'scatter', mode = 'lines', line=list(width=1.5, color=COLOR_PP), yaxis = "y2") %>% 
              add_segments(x = min(pData$Distance), xend = max(pData$Distance), y = ppMeanBefore, yend = ppMeanBefore, 
                           yaxis = "y2", name="Mean PP (Before Incident)",
                           line=list(color=COLOR_PP, dash = 'dot')) %>%
              add_segments(x = min(pData$Distance), xend = max(pData$Distance), y = ppMeanAfter, yend = ppMeanAfter, 
                           yaxis = "y2", name="Mean PP (After Incident)",
                           line=list(color="darkred", dash = 'dot')) %>%
              # add_segments(x = min(pData$Distance) - 0.1, xend = max(pData$Distance), y = pp_baseline[[p]], yend = pp_baseline[[p]], 
              #              yaxis = "y2", name="Baseline PP (from Drive 1)",
              #              line=list(color="blue", dash = 'dot')) %>%
    
              layout(
                title=paste0("Subject #", p, " (Stressor=", activity_names[[p]], ")"), 
                xaxis=list(title="Distance [m]", range=c(0)), 
                yaxis=y1, 
                yaxis2=y2, 
                margin = list(l = 50, r = 50, b = 50, t = 50, pad = 4),
                shapes = list(
                  # Holistic period
                  list(type = "rect", fillcolor = "red", 
                       line = list(color = "red"), opacity = 0.3,
                      x0 = incident_starting_time, x1 = incident_ending_time, xref = "x",
                      y0 = 0, y1 = 100, yref = "y"),
                  # Stressor period
                  list(type = "rect", fillcolor = "yellow", 
                       line = list(color = "yellow"), opacity = 0.1,
                      x0 = stressor_start_times[[p]], x1 = incident_starting_time, xref = "x",
                      y0 = 0, y1 = 100, yref = "y"),
                  list(type = "rect", fillcolor = "yellow", 
                       line = list(color = "yellow"), opacity = 0.1,
                      x0 = incident_ending_time, x1 = stressor_end_times[[p]], xref = "x",
                      y0 = 0, y1 = 100, yref = "y")
                ),
                legend = list(x = 0.1, y = 1, bgcolor = "rgba(0,0,0,0)", title="Metric"),
                autosize = F
              )
  
  # orca(plot_PP, fname)
  idx <- idx + 1
  plt_AllAcc[[p]] <- plot_Acc
}

htmltools::tagList(plt_AllAcc)
# for (p in persons) {
#   # Save image
#   orca(plt_AllAcc[[p]], file = paste0("../plots/drive/Drive_4/T0", p, ".png"), scale = 2)
# }
idx <- 1
behavioralColumns <- c("Subject", 
                       "Brake_u", 
                       "Brake_std", 
                       "PP_before",
                       "PP_u",  
                       "PP_std",
                       "PP_dev")
behavioralMatrix <- matrix(nrow=length(persons), ncol = length(behavioralColumns))

# Careful about Subject 09
# selected_persons <- persons[persons != "09"]

for (p in persons) {
  pData <- all_Drive4[all_Drive4$Subject==as.integer(p) | all_Drive4$Subject==p,]
  
  incident_starting_time <- acc_start_times[[p]] # starting_points[idx]
  incident_ending_time <- acc_end_times[[p]]
  
  from_time <- ifelse(incident_starting_time - PREV_DISTANCE >= 0, incident_starting_time - PREV_DISTANCE, 0)
  to_time <- complete_times[[p]]
    
  dfBefore <- pData[pData$Distance < incident_starting_time & pData$Distance >= from_time,]
  dfAfter <- pData[pData$Distance >= incident_starting_time + DELAY_DISTANCE  & pData$Distance <= to_time,]
  
  # diffSpeed <- mean(dfAfter$Speed) - mean(dfBefore$Speed)
  brakeMean <- mean(dfAfter$Braking)
  brakeStd <- mean(dfAfter$Braking)
  
  ppMean <- mean(dfAfter$ppLogNormalized)
  ppBefore <- mean(dfBefore$ppLogNormalized)
  ppStd <- sd(dfAfter$ppLogNormalized)
  
  mid_avg <- (pp_baseline[[p]] + mean(dfBefore$ppLogNormalized)) / 2
    
  diffPP <- mean(dfAfter$ppLogNormalized) - mean(dfBefore$ppLogNormalized)
  
  behavioralMatrix[idx, ] <- c(p, 
                               round(brakeMean, digits=5), 
                               round(brakeStd, digits=5),
                               round(ppBefore, digits=5),
                               round(ppMean, digits = 5),
                               round(ppStd, digits=5),
                               round(diffPP, digits=5))
  idx <- idx + 1
}

# behavioralMatrix

behavioralDf <- as.data.frame(behavioralMatrix, stringsAsFactors=FALSE)
names(behavioralDf) <- behavioralColumns

behavioralDf
NA
clusteringDf <- behavioralDf
clusteringDf$Subject <- NULL
# clusteringDf$PP_dev_norm <- as.numeric(clusteringDf$PP_dev) / as.numeric(clusteringDf$PP_u)
# clusteringDf$PP_std_norm <- as.numeric(clusteringDf$PP_std) / as.numeric(clusteringDf$PP_u)
clusteringDf$Brake_u <- NULL
clusteringDf$Brake_std <- NULL
clusteringDf$PP_before <- NULL
clusteringDf$PP_u <- NULL
clusteringDf$PP_std <- NULL
# clusteringDf$PP_dev <- NULL

rownames(clusteringDf) <- paste0("#", persons)

for (col in names(clusteringDf)) {
  clusteringDf[,col] <- as.numeric(as.character(clusteringDf[, col]))
  # clusteringDf[,col] <- scale(clusteringDf[,col])
}
clusteringDf
dfActivity <- all_Drive4[all_Drive4$Time==60,] %>% select(c("Subject", "Activity"))
dfActivity$ActivityName <- sapply(dfActivity$Activity, getActivityName)
dfActivity$Subject <- as.factor(dfActivity$Subject)
rownames(dfActivity) <- NULL
dfActivity %>% select(c("Subject", "ActivityName"))
library(dendextend)

NUMBER_OF_CLUSTERS = 3

color_darkpink = "#e75480"
CLUSTER_BRANCH_COLORS <- c("blue", "red", color_darkpink)[1:NUMBER_OF_CLUSTERS]
CLUSTER_LABEL_COLORS <- c("blue", "red", color_darkpink)[1:NUMBER_OF_CLUSTERS]

behavioralMatrixClustering <- as.matrix(clusteringDf)
rownames(behavioralMatrixClustering) <- paste0(dfActivity$ActivityName, " - #", persons)
distMatrix <- dist(behavioralMatrixClustering, method="manhattan")
hresults <- distMatrix %>% hclust

hc <- hresults %>% 
      as.dendrogram %>%
      set("nodes_cex", NUMBER_OF_CLUSTERS) %>%
      set("labels_col", value = CLUSTER_LABEL_COLORS, k=NUMBER_OF_CLUSTERS) %>%
      # set("leaves_pch", 19) %>%
      # set("leaves_col", value = c("gray"), k=NUMBER_OF_CLUSTERS) %>%    
      set("branches_k_color", value=CLUSTER_BRANCH_COLORS, k=NUMBER_OF_CLUSTERS)

plot(hc)
legend("topright", 
     title="Drive=Failure \nChange of Arousal",
     legend = c("Exceptional Increase" , "Noticable Increase" , "No-change or Decrease"), 
     col = c("red", "pink" , "blue"),
     pch = c(20,20,20), bty = "n",  pt.cex = 1.5, cex = 0.8 , 
     text.col = "black", horiz = FALSE, inset = c(0.0, 0.1))

NUMBER_OF_CLUSTERS = 2

color_darkpink = "#e75480"
CLUSTER_BRANCH_COLORS <- c("blue", "red", color_darkpink)[1:NUMBER_OF_CLUSTERS]
CLUSTER_LABEL_COLORS <- c("blue", "red", color_darkpink)[1:NUMBER_OF_CLUSTERS]

behavioralMatrixClustering <- as.matrix(clusteringDf)
rownames(behavioralMatrixClustering) <- paste0(dfActivity$ActivityName, " - #", persons)
distMatrix <- dist(behavioralMatrixClustering, method="manhattan", diag = T)
hresults <- distMatrix %>% hclust(method="average")

hc <- hresults %>% 
      as.dendrogram %>%
      set("nodes_cex", NUMBER_OF_CLUSTERS) %>%
      set("labels_col", value = CLUSTER_LABEL_COLORS, k=NUMBER_OF_CLUSTERS) %>%
      # set("leaves_pch", 19) %>%
      # set("leaves_col", value = c("gray"), k=NUMBER_OF_CLUSTERS) %>%    
      set("branches_k_color", value=CLUSTER_BRANCH_COLORS, k=NUMBER_OF_CLUSTERS)

plot(hc)
legend("topright", 
     title="Drive=Failure \nChange of Arousal",
     legend = c("Accelerophobia" , "Normal"), 
     col = c("red", "blue"),
     pch = c(20,20,20), bty = "n",  pt.cex = 1.5, cex = 0.8 , 
     text.col = "black", horiz = FALSE, inset = c(0.0, 0.1))

# Store clustering data
fPath <- str_interp("../data/processed/analysis/TT1_Drive_4_PP.csv")
dfx <- clusteringDf
dfx <- cbind(persons, as.numeric(behavioralDf$PP_before), as.numeric(behavioralDf$PP_u), dfx, dfActivity$ActivityName)
names(dfx) <- c("Subject", "PP_Prior", "PP_After", "PP_Dev", "Activity")

# Normalize
dfx <- dfx %>% mutate(PP_Dev_Normalized = ifelse(PP_Prior > 0, PP_After, PP_After - PP_Prior))

write.csv(dfx, fPath, row.names = F)
library(cluster)
fit <- kmeans(clusteringDf, 2)
clusplot(clusteringDf, fit$cluster, color=TRUE, shade=TRUE,
   labels=2, lines=0)

silhouette_score <- function(k){
  km <- kmeans(clusteringDf, centers = k, nstart=25)
  ss <- silhouette(km$cluster, dist(clusteringDf))
  mean(ss[, 3])
}
k <- 2:10
avg_sil <- sapply(k, silhouette_score)
plot(k, type='b', avg_sil, xlab='Number of clusters', ylab='Average Silhouette Scores', frame=FALSE)

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKYGBge3J9CnNvdXJjZSgnLi4vc2V0dGluZ3Mvc2V0dGluZ3MuUicpCnNvdXJjZSgnY29tbW9uRnVuY3Rpb25zLlInKQpgYGAKCmBgYHtyfQpwZXJzb25zIDwtIFNFTEVDVEVEX1NVQkpFQ1RTCgphbGxfRHJpdmU0IDwtIHJlYWQuY3N2KCcuLi9kYXRhL3Byb2Nlc3NlZC9kaXN0YW5jZXdpc2UvVFQxX0RyaXZlXzRfMzBtXzMwbS5jc3YnKQphbGxfRHJpdmU0JFN1YmplY3QgPC0gYXMuZmFjdG9yKGFsbF9Ecml2ZTQkU3ViamVjdCkKYWxsX0RyaXZlNCRsb2dQZXJzcGlyYXRpb24gPC0gbG9nKGFsbF9Ecml2ZTQkUGVyc3BpcmF0aW9uKQoKIyBzdGFydGluZ19wb2ludHMgPSBjKCA2NjkgLCA2NjggLCA2NzYgLCA2ODcgLCA2ODAgLCAgNjc2ICwgIDY3OCAsCiMgICAgICAgICAgICAgICAgICAgICAgNjkzICwgNzIyICwgNzIzICwgNjc3ICwgNjc5ICwgIDcxMSAsICA3MDcgLCAgCiMgICAgICAgICAgICAgICAgICAgICAgNjk5ICwgNjc5ICwgNjg0ICwgNjg4ICwgNjg2ICwgIDY5NiAsICA3MDIgKQojIAojIGVuZGluZ19wb2ludHMgICA9IGMoIDc0MSAsIDc4NiAsIDc0OSAsIDc4MiAsIDczNiAsICA3NTYgLCAgNzY4ICwgIAojICAgICAgICAgICAgICAgICAgICAgIDgxMiAsIDg1MyAsIDc5MiAsIDc4MyAsIDc3MiAsICA3OTkgLCAgNzgxICwgIAojICAgICAgICAgICAgICAgICAgICAgIDc3NyAsIDc2MyAsIDc5NSAsIDc5MSAsIDgzMiAsICA3NTUgLCAgNzU4ICkKCnBlYWtfcG9pbnRzICAgICA9IGMoIDY3ICwgIDg2ICwgIDczICwgIDczICwgIDczICwgIDY0ICwgIDczICwgIAogICAgICAgICAgICAgICAgICAgICA3OSAsICA2OSAsICA2NCAsICA2OCAsICA2NyAsICA3NyAsICA2OCAsICAKICAgICAgICAgICAgICAgICAgICAgODIgLCAgNjcgLCAgNzIgLCAgNzIgLCAgNzEgLCAgNjggLCAgNjQgKQoKIyBEcml2aW5nIHRpbWUKZHJpdmluZ190aW1lcyA9IHZlY3Rvcihtb2RlPSJsaXN0IiwgbGVuZ3RoID0gbGVuZ3RoKHBlcnNvbnMpKQpuYW1lcyhkcml2aW5nX3RpbWVzKSA8LSBwZXJzb25zCgphY3Rpdml0eV9uYW1lcyA9IHZlY3Rvcihtb2RlPSJsaXN0IiwgbGVuZ3RoID0gbGVuZ3RoKHBlcnNvbnMpKQpuYW1lcyhhY3Rpdml0eV9uYW1lcykgPC0gcGVyc29ucwoKYWNjX3N0YXJ0X3RpbWVzID0gdmVjdG9yKG1vZGU9Imxpc3QiLCBsZW5ndGggPSBsZW5ndGgocGVyc29ucykpCm5hbWVzKGFjY19zdGFydF90aW1lcykgPC0gcGVyc29ucwphY2NfZW5kX3RpbWVzID0gdmVjdG9yKG1vZGU9Imxpc3QiLCBsZW5ndGggPSBsZW5ndGgocGVyc29ucykpCm5hbWVzKGFjY19lbmRfdGltZXMpIDwtIHBlcnNvbnMKCnN0cmVzc29yX3N0YXJ0X3RpbWVzID0gdmVjdG9yKG1vZGU9Imxpc3QiLCBsZW5ndGggPSBsZW5ndGgocGVyc29ucykpCm5hbWVzKHN0cmVzc29yX3N0YXJ0X3RpbWVzKSA8LSBwZXJzb25zCnN0cmVzc29yX2VuZF90aW1lcyA9IHZlY3Rvcihtb2RlPSJsaXN0IiwgbGVuZ3RoID0gbGVuZ3RoKHBlcnNvbnMpKQpuYW1lcyhzdHJlc3Nvcl9lbmRfdGltZXMpIDwtIHBlcnNvbnMKCmNvbXBsZXRlX3RpbWVzID0gdmVjdG9yKG1vZGU9Imxpc3QiLCBsZW5ndGggPSBsZW5ndGgocGVyc29ucykpCm5hbWVzKGNvbXBsZXRlX3RpbWVzKSA8LSBwZXJzb25zCgpkYXRhX2Jhc2VsaW5lID0gdmVjdG9yKG1vZGU9Imxpc3QiLCBsZW5ndGg9bGVuZ3RoKHBlcnNvbnMpKQpwcF9iYXNlbGluZSA9IHZlY3Rvcihtb2RlPSJsaXN0IiwgbGVuZ3RoPWxlbmd0aChwZXJzb25zKSkKCm5hbWVzKGRhdGFfYmFzZWxpbmUpIDwtIHBlcnNvbnMKbmFtZXMocHBfYmFzZWxpbmUpIDwtIHBlcnNvbnMKCiMgTnVtYmVyIG9mIHBlYWtzCgpQUkVWX0RJU1RBTkNFID0gMzAwClRSQUNLSU5HX0RJU1RBTkNFID0gNjAKRFJJVkVfTU9ERSA9IDQKYGBgCgpgYGB7cn0KZ2V0QWN0aXZpdHlOYW1lIDwtIGZ1bmN0aW9uKHgsIGZ1bGxuYW1lPUYpIHsKICBpZih4ID09IDEpIHJldHVybihpZmVsc2UoZnVsbG5hbWUsICJOb3JtYWwiLCAiTk8iKSkKICBpZih4ID09IDIpIHJldHVybihpZmVsc2UoZnVsbG5hbWUsICJDb2duaXRpdmUiLCAiQyIpKQogIGlmKHggPT0gMykgcmV0dXJuKGlmZWxzZShmdWxsbmFtZSwgIk1vdG9yaWMiLCAiTSIpKQp9Cgpmb3IgKHAgaW4gcGVyc29ucykgewogIHBEYXRhIDwtIGFsbF9Ecml2ZTRbYWxsX0RyaXZlNCRTdWJqZWN0PT1hcy5pbnRlZ2VyKHApIHwgYWxsX0RyaXZlNCRTdWJqZWN0PT1wLF0KICBwQWNjIDwtIHBEYXRhW3BEYXRhJEZhaWx1cmU+MC41LF0gIyBGYWlsdXJlID0gMQogIGFjY19zdGFydF90aW1lc1tbcF1dIDwtIG1pbihwQWNjJERpc3RhbmNlKQogIGFjY19lbmRfdGltZXNbW3BdXSA8LSBtYXgocEFjYyREaXN0YW5jZSkKICAKICBhY3Rpdml0eV9uYW1lc1tbcF1dIDwtIGdldEFjdGl2aXR5TmFtZShwRGF0YVtwRGF0YSRUaW1lPT02MCxdJEFjdGl2aXR5LCBmdWxsbmFtZSA9IFQpCiAgCiAgcFN0cmVzc29yID0gcERhdGFbcERhdGEkQWN0aXZpdHk+MS41LF0gIyBTdHJlc3NvciA9IDIsIDMKICBpZiAobnJvdyhwU3RyZXNzb3IpID4gMCkgewogICAgc3RyZXNzb3Jfc3RhcnRfdGltZXNbW3BdXSA8LSBtaW4ocFN0cmVzc29yJERpc3RhbmNlKQogICAgc3RyZXNzb3JfZW5kX3RpbWVzW1twXV0gPC0gbWF4KHBTdHJlc3NvciREaXN0YW5jZSkKICB9IGVsc2UgewogICAgc3RyZXNzb3Jfc3RhcnRfdGltZXNbW3BdXSA8LSBOVUxMCiAgICBzdHJlc3Nvcl9lbmRfdGltZXNbW3BdXSA8LSBOVUxMCiAgfQp9CmBgYAoKYGBge3J9CkRFTEFZX0RJU1RBTkNFIDwtIDEwCgppZHggPC0gMQpwbHRfQWxsQWNjIDwtIHZlY3Rvcihtb2RlPSJsaXN0IiwgbGVuZ3RoPWxlbmd0aChwZXJzb25zKSkgCm5hbWVzKHBsdF9BbGxBY2MpIDwtIHBlcnNvbnMKCkNPTE9SX0FDQyA9ICIjMDJBM0M4IgpDT0xPUl9QUCA9ICIjRjI4RThFIgpDT0xPUl9CUkFLRSA9ICIjODg4ODg4IgoKeTEgPC0gbGlzdCgKICB0aWNrZm9udCA9IGxpc3QoY29sb3IgPSBDT0xPUl9BQ0MpLAogIHRpdGxlPSJEZWdyZWUiLAogIHJhbmdlPWMoMCwgMTAwKQopCnkyIDwtIGxpc3QoCiAgdGlja2ZvbnQgPSBsaXN0KGNvbG9yID0gQ09MT1JfUFApLAogIG92ZXJsYXlpbmcgPSAieSIsCiAgc2lkZSA9ICJyaWdodCIsCiAgdGl0bGUgPSAiTG9nIFBlcnNwaXJhdGlvbiIsCiAgc2hvd2dyaWQgPSBGQUxTRSwKICByYW5nZT1jKG1pbihhbGxfRHJpdmU0JHBwTG9nTm9ybWFsaXplZCksIG1heChhbGxfRHJpdmU0JHBwTG9nTm9ybWFsaXplZCkpCikKICAKZm9yIChwIGluIHBlcnNvbnMpIHsKICBwRGF0YSA8LSBhbGxfRHJpdmU0W2FsbF9Ecml2ZTQkU3ViamVjdD09YXMuaW50ZWdlcihwKSB8IGFsbF9Ecml2ZTQkU3ViamVjdD09cCxdCiAgCiAgIyBCYXNlbGluZQogIGRhdGFfYmFzZWxpbmVbW3BdXSA8LSByZWFkLmNzdihzdHJfaW50ZXJwKCIuLi9kYXRhL3Byb2Nlc3NlZC9kcml2ZXMvVDAke3BlcnNvbn0vVDAke3BlcnNvbn1fRHJpdmVfMS5jc3YiLCBsaXN0KHBlcnNvbj1wKSkpCiAgIyBDb21wdXRlIHRoZSBtZWFuCiAgcF9wcF9uciA8LSBkYXRhX2Jhc2VsaW5lW1twXV0kUGVyc3BpcmF0aW9uCiAgcF9wcF9uciA8LSBwX3BwX25yWyFpcy5uYShwX3BwX25yKV0KICBwcF9iYXNlbGluZVtbcF1dIDwtIGxvZyhtZWFuKHBfcHBfbnIpKQogIAogICMgSW5jaWRlbnQKICBkcml2aW5nX3RpbWVzW1twXV0gPC0gbWF4KHBEYXRhJERpc3RhbmNlKQogIAogIGluY2lkZW50X3N0YXJ0aW5nX3RpbWUgPC0gYWNjX3N0YXJ0X3RpbWVzW1twXV0gIyBzdGFydGluZ19wb2ludHNbaWR4XQogIGluY2lkZW50X2VuZGluZ190aW1lIDwtIGFjY19lbmRfdGltZXNbW3BdXQogIGNvbXBsZXRlX3RpbWVzW1twXV0gPC0gaWZlbHNlKGluY2lkZW50X3N0YXJ0aW5nX3RpbWUgKyBUUkFDS0lOR19ESVNUQU5DRSA+IGRyaXZpbmdfdGltZXNbW3BdXSwgZHJpdmluZ190aW1lc1tbcF1dLCBpbmNpZGVudF9zdGFydGluZ190aW1lICsgVFJBQ0tJTkdfRElTVEFOQ0UpCiAgCiAgZnJvbV90aW1lIDwtIGlmZWxzZShpbmNpZGVudF9zdGFydGluZ190aW1lIC0gUFJFVl9ESVNUQU5DRSA+PSAwLCBpbmNpZGVudF9zdGFydGluZ190aW1lIC0gUFJFVl9ESVNUQU5DRSwgMCkKICB0b190aW1lIDwtIGNvbXBsZXRlX3RpbWVzW1twXV0KICAKICAjIHByaW50KHBhc3RlKCJGcm9tIiwgZnJvbV90aW1lKSkKICAjIHByaW50KHBhc3RlKCJJbmNpZGVudCIsIGluY2lkZW50X3N0YXJ0aW5nX3RpbWUpKQogICMgcHJpbnQocGFzdGUoIlRvIiwgdG9fdGltZSkpCiAgCiAgICAKICBwRGF0YUJlZm9yZSA8LSBwRGF0YVtwRGF0YSREaXN0YW5jZSA8IGluY2lkZW50X3N0YXJ0aW5nX3RpbWUgJiBwRGF0YSREaXN0YW5jZSA+PSBmcm9tX3RpbWUsXQogIHBEYXRhQWZ0ZXIgPC0gcERhdGFbcERhdGEkRGlzdGFuY2UgPj0gaW5jaWRlbnRfc3RhcnRpbmdfdGltZSArIERFTEFZX0RJU1RBTkNFICYgcERhdGEkRGlzdGFuY2UgPD0gdG9fdGltZSxdCiAgCiAgIyBwcmludChucm93KHBEYXRhQmVmb3JlKSkKICAjIHByaW50KG5yb3cocERhdGFBZnRlcikpCiAgCiAgcHBNZWFuQmVmb3JlIDwtIG1lYW4ocERhdGFCZWZvcmUkcHBMb2dOb3JtYWxpemVkKQogIHBwTWVhbkFmdGVyIDwtIG1lYW4ocERhdGFBZnRlciRwcExvZ05vcm1hbGl6ZWQpCiAgCiAgZGlyLmNyZWF0ZShmaWxlLnBhdGgoJy4uL2ZpZ3VyZXMvZHJpdmUvJywgcGFzdGUwKCdEcml2ZV8nLCBEUklWRV9NT0RFKSksIHNob3dXYXJuaW5ncyA9IEZBTFNFKQogIGZuYW1lIDwtIHN0cl9pbnRlcnAoJy4uL2ZpZ3VyZXMvZHJpdmUvRHJpdmVfJHtkcml2ZX0vUCR7cGVyc29ufS5zdmcnLCBsaXN0KGRyaXZlPURSSVZFX01PREUsIHBlcnNvbj1wKSkgCiAgCiAgcERhdGEgPC0gcERhdGFbcERhdGEkRGlzdGFuY2UgPj0gZnJvbV90aW1lLF0KICBwbG90X0FjYyA8LSBwbG90X2x5KHBEYXRhLCB4ID0gfkRpc3RhbmNlLCBoZWlnaHQ9NDAwLCB3aWR0aD05MDApICU+JQogICAgICAgICAgICAgIGFkZF90cmFjZShuYW1lPSJBY2NlbGVyYXRpb24iLCB5ID0gfkFjY2VsZXJhdGlvbiwgdHlwZSA9ICdzY2F0dGVyJywgbW9kZSA9ICdsaW5lcycsIGxpbmU9bGlzdCh3aWR0aD0xLjUsIGNvbG9yPUNPTE9SX0FDQykpICU+JSAKICAgICAgICAgICAgICBhZGRfdHJhY2UobmFtZT0iQnJha2UiLCB5ID0gfkJyYWtpbmcsIHR5cGUgPSAnc2NhdHRlcicsIG1vZGUgPSAnbGluZXMnLCBsaW5lPWxpc3Qod2lkdGg9MS41LCBjb2xvcj1DT0xPUl9CUkFLRSkpICU+JQogICAgICAgICAgICAgIGFkZF90cmFjZShuYW1lPSJQUCIsIHkgPSB+cHBMb2dOb3JtYWxpemVkLCB0eXBlID0gJ3NjYXR0ZXInLCBtb2RlID0gJ2xpbmVzJywgbGluZT1saXN0KHdpZHRoPTEuNSwgY29sb3I9Q09MT1JfUFApLCB5YXhpcyA9ICJ5MiIpICU+JSAKICAgICAgICAgICAgICBhZGRfc2VnbWVudHMoeCA9IG1pbihwRGF0YSREaXN0YW5jZSksIHhlbmQgPSBtYXgocERhdGEkRGlzdGFuY2UpLCB5ID0gcHBNZWFuQmVmb3JlLCB5ZW5kID0gcHBNZWFuQmVmb3JlLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgeWF4aXMgPSAieTIiLCBuYW1lPSJNZWFuIFBQIChCZWZvcmUgSW5jaWRlbnQpIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZT1saXN0KGNvbG9yPUNPTE9SX1BQLCBkYXNoID0gJ2RvdCcpKSAlPiUKICAgICAgICAgICAgICBhZGRfc2VnbWVudHMoeCA9IG1pbihwRGF0YSREaXN0YW5jZSksIHhlbmQgPSBtYXgocERhdGEkRGlzdGFuY2UpLCB5ID0gcHBNZWFuQWZ0ZXIsIHllbmQgPSBwcE1lYW5BZnRlciwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHlheGlzID0gInkyIiwgbmFtZT0iTWVhbiBQUCAoQWZ0ZXIgSW5jaWRlbnQpIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZT1saXN0KGNvbG9yPSJkYXJrcmVkIiwgZGFzaCA9ICdkb3QnKSkgJT4lCiAgICAgICAgICAgICAgIyBhZGRfc2VnbWVudHMoeCA9IG1pbihwRGF0YSREaXN0YW5jZSkgLSAwLjEsIHhlbmQgPSBtYXgocERhdGEkRGlzdGFuY2UpLCB5ID0gcHBfYmFzZWxpbmVbW3BdXSwgeWVuZCA9IHBwX2Jhc2VsaW5lW1twXV0sIAogICAgICAgICAgICAgICMgICAgICAgICAgICAgIHlheGlzID0gInkyIiwgbmFtZT0iQmFzZWxpbmUgUFAgKGZyb20gRHJpdmUgMSkiLAogICAgICAgICAgICAgICMgICAgICAgICAgICAgIGxpbmU9bGlzdChjb2xvcj0iYmx1ZSIsIGRhc2ggPSAnZG90JykpICU+JQogICAgCiAgICAgICAgICAgICAgbGF5b3V0KAogICAgICAgICAgICAgICAgdGl0bGU9cGFzdGUwKCJTdWJqZWN0ICMiLCBwLCAiIChTdHJlc3Nvcj0iLCBhY3Rpdml0eV9uYW1lc1tbcF1dLCAiKSIpLCAKICAgICAgICAgICAgICAgIHhheGlzPWxpc3QodGl0bGU9IkRpc3RhbmNlIFttXSIsIHJhbmdlPWMoMCkpLCAKICAgICAgICAgICAgICAgIHlheGlzPXkxLCAKICAgICAgICAgICAgICAgIHlheGlzMj15MiwgCiAgICAgICAgICAgICAgICBtYXJnaW4gPSBsaXN0KGwgPSA1MCwgciA9IDUwLCBiID0gNTAsIHQgPSA1MCwgcGFkID0gNCksCiAgICAgICAgICAgICAgICBzaGFwZXMgPSBsaXN0KAogICAgICAgICAgICAgICAgICAjIEhvbGlzdGljIHBlcmlvZAogICAgICAgICAgICAgICAgICBsaXN0KHR5cGUgPSAicmVjdCIsIGZpbGxjb2xvciA9ICJyZWQiLCAKICAgICAgICAgICAgICAgICAgICAgICBsaW5lID0gbGlzdChjb2xvciA9ICJyZWQiKSwgb3BhY2l0eSA9IDAuMywKICAgICAgICAgICAgICAgICAgICAgIHgwID0gaW5jaWRlbnRfc3RhcnRpbmdfdGltZSwgeDEgPSBpbmNpZGVudF9lbmRpbmdfdGltZSwgeHJlZiA9ICJ4IiwKICAgICAgICAgICAgICAgICAgICAgIHkwID0gMCwgeTEgPSAxMDAsIHlyZWYgPSAieSIpLAogICAgICAgICAgICAgICAgICAjIFN0cmVzc29yIHBlcmlvZAogICAgICAgICAgICAgICAgICBsaXN0KHR5cGUgPSAicmVjdCIsIGZpbGxjb2xvciA9ICJ5ZWxsb3ciLCAKICAgICAgICAgICAgICAgICAgICAgICBsaW5lID0gbGlzdChjb2xvciA9ICJ5ZWxsb3ciKSwgb3BhY2l0eSA9IDAuMSwKICAgICAgICAgICAgICAgICAgICAgIHgwID0gc3RyZXNzb3Jfc3RhcnRfdGltZXNbW3BdXSwgeDEgPSBpbmNpZGVudF9zdGFydGluZ190aW1lLCB4cmVmID0gIngiLAogICAgICAgICAgICAgICAgICAgICAgeTAgPSAwLCB5MSA9IDEwMCwgeXJlZiA9ICJ5IiksCiAgICAgICAgICAgICAgICAgIGxpc3QodHlwZSA9ICJyZWN0IiwgZmlsbGNvbG9yID0gInllbGxvdyIsIAogICAgICAgICAgICAgICAgICAgICAgIGxpbmUgPSBsaXN0KGNvbG9yID0gInllbGxvdyIpLCBvcGFjaXR5ID0gMC4xLAogICAgICAgICAgICAgICAgICAgICAgeDAgPSBpbmNpZGVudF9lbmRpbmdfdGltZSwgeDEgPSBzdHJlc3Nvcl9lbmRfdGltZXNbW3BdXSwgeHJlZiA9ICJ4IiwKICAgICAgICAgICAgICAgICAgICAgIHkwID0gMCwgeTEgPSAxMDAsIHlyZWYgPSAieSIpCiAgICAgICAgICAgICAgICApLAogICAgICAgICAgICAgICAgbGVnZW5kID0gbGlzdCh4ID0gMC4xLCB5ID0gMSwgYmdjb2xvciA9ICJyZ2JhKDAsMCwwLDApIiwgdGl0bGU9Ik1ldHJpYyIpLAogICAgICAgICAgICAgICAgYXV0b3NpemUgPSBGCiAgICAgICAgICAgICAgKQogIAogICMgb3JjYShwbG90X1BQLCBmbmFtZSkKICBpZHggPC0gaWR4ICsgMQogIHBsdF9BbGxBY2NbW3BdXSA8LSBwbG90X0FjYwp9CgpodG1sdG9vbHM6OnRhZ0xpc3QocGx0X0FsbEFjYykKYGBgCgpgYGB7ciwgd2FybmluZz1GQUxTRX0KIyBmb3IgKHAgaW4gcGVyc29ucykgewojICAgIyBTYXZlIGltYWdlCiMgICBvcmNhKHBsdF9BbGxBY2NbW3BdXSwgZmlsZSA9IHBhc3RlMCgiLi4vcGxvdHMvZHJpdmUvRHJpdmVfNC9UMCIsIHAsICIucG5nIiksIHNjYWxlID0gMikKIyB9CmBgYAoKYGBge3J9CmlkeCA8LSAxCmJlaGF2aW9yYWxDb2x1bW5zIDwtIGMoIlN1YmplY3QiLCAKICAgICAgICAgICAgICAgICAgICAgICAiQnJha2VfdSIsIAogICAgICAgICAgICAgICAgICAgICAgICJCcmFrZV9zdGQiLCAKICAgICAgICAgICAgICAgICAgICAgICAiUFBfYmVmb3JlIiwKICAgICAgICAgICAgICAgICAgICAgICAiUFBfdSIsICAKICAgICAgICAgICAgICAgICAgICAgICAiUFBfc3RkIiwKICAgICAgICAgICAgICAgICAgICAgICAiUFBfZGV2IikKYmVoYXZpb3JhbE1hdHJpeCA8LSBtYXRyaXgobnJvdz1sZW5ndGgocGVyc29ucyksIG5jb2wgPSBsZW5ndGgoYmVoYXZpb3JhbENvbHVtbnMpKQoKIyBDYXJlZnVsIGFib3V0IFN1YmplY3QgMDkKIyBzZWxlY3RlZF9wZXJzb25zIDwtIHBlcnNvbnNbcGVyc29ucyAhPSAiMDkiXQoKZm9yIChwIGluIHBlcnNvbnMpIHsKICBwRGF0YSA8LSBhbGxfRHJpdmU0W2FsbF9Ecml2ZTQkU3ViamVjdD09YXMuaW50ZWdlcihwKSB8IGFsbF9Ecml2ZTQkU3ViamVjdD09cCxdCiAgCiAgaW5jaWRlbnRfc3RhcnRpbmdfdGltZSA8LSBhY2Nfc3RhcnRfdGltZXNbW3BdXSAjIHN0YXJ0aW5nX3BvaW50c1tpZHhdCiAgaW5jaWRlbnRfZW5kaW5nX3RpbWUgPC0gYWNjX2VuZF90aW1lc1tbcF1dCiAgCiAgZnJvbV90aW1lIDwtIGlmZWxzZShpbmNpZGVudF9zdGFydGluZ190aW1lIC0gUFJFVl9ESVNUQU5DRSA+PSAwLCBpbmNpZGVudF9zdGFydGluZ190aW1lIC0gUFJFVl9ESVNUQU5DRSwgMCkKICB0b190aW1lIDwtIGNvbXBsZXRlX3RpbWVzW1twXV0KICAgIAogIGRmQmVmb3JlIDwtIHBEYXRhW3BEYXRhJERpc3RhbmNlIDwgaW5jaWRlbnRfc3RhcnRpbmdfdGltZSAmIHBEYXRhJERpc3RhbmNlID49IGZyb21fdGltZSxdCiAgZGZBZnRlciA8LSBwRGF0YVtwRGF0YSREaXN0YW5jZSA+PSBpbmNpZGVudF9zdGFydGluZ190aW1lICsgREVMQVlfRElTVEFOQ0UgICYgcERhdGEkRGlzdGFuY2UgPD0gdG9fdGltZSxdCiAgCiAgIyBkaWZmU3BlZWQgPC0gbWVhbihkZkFmdGVyJFNwZWVkKSAtIG1lYW4oZGZCZWZvcmUkU3BlZWQpCiAgYnJha2VNZWFuIDwtIG1lYW4oZGZBZnRlciRCcmFraW5nKQogIGJyYWtlU3RkIDwtIG1lYW4oZGZBZnRlciRCcmFraW5nKQogIAogIHBwTWVhbiA8LSBtZWFuKGRmQWZ0ZXIkcHBMb2dOb3JtYWxpemVkKQogIHBwQmVmb3JlIDwtIG1lYW4oZGZCZWZvcmUkcHBMb2dOb3JtYWxpemVkKQogIHBwU3RkIDwtIHNkKGRmQWZ0ZXIkcHBMb2dOb3JtYWxpemVkKQogIAogIG1pZF9hdmcgPC0gKHBwX2Jhc2VsaW5lW1twXV0gKyBtZWFuKGRmQmVmb3JlJHBwTG9nTm9ybWFsaXplZCkpIC8gMgogICAgCiAgZGlmZlBQIDwtIG1lYW4oZGZBZnRlciRwcExvZ05vcm1hbGl6ZWQpIC0gbWVhbihkZkJlZm9yZSRwcExvZ05vcm1hbGl6ZWQpCiAgCiAgYmVoYXZpb3JhbE1hdHJpeFtpZHgsIF0gPC0gYyhwLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvdW5kKGJyYWtlTWVhbiwgZGlnaXRzPTUpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvdW5kKGJyYWtlU3RkLCBkaWdpdHM9NSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByb3VuZChwcEJlZm9yZSwgZGlnaXRzPTUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcm91bmQocHBNZWFuLCBkaWdpdHMgPSA1KSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvdW5kKHBwU3RkLCBkaWdpdHM9NSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByb3VuZChkaWZmUFAsIGRpZ2l0cz01KSkKICBpZHggPC0gaWR4ICsgMQp9CgojIGJlaGF2aW9yYWxNYXRyaXgKCmJlaGF2aW9yYWxEZiA8LSBhcy5kYXRhLmZyYW1lKGJlaGF2aW9yYWxNYXRyaXgsIHN0cmluZ3NBc0ZhY3RvcnM9RkFMU0UpCm5hbWVzKGJlaGF2aW9yYWxEZikgPC0gYmVoYXZpb3JhbENvbHVtbnMKCmJlaGF2aW9yYWxEZgoKYGBgCgoKYGBge3J9CmNsdXN0ZXJpbmdEZiA8LSBiZWhhdmlvcmFsRGYKY2x1c3RlcmluZ0RmJFN1YmplY3QgPC0gTlVMTAojIGNsdXN0ZXJpbmdEZiRQUF9kZXZfbm9ybSA8LSBhcy5udW1lcmljKGNsdXN0ZXJpbmdEZiRQUF9kZXYpIC8gYXMubnVtZXJpYyhjbHVzdGVyaW5nRGYkUFBfdSkKIyBjbHVzdGVyaW5nRGYkUFBfc3RkX25vcm0gPC0gYXMubnVtZXJpYyhjbHVzdGVyaW5nRGYkUFBfc3RkKSAvIGFzLm51bWVyaWMoY2x1c3RlcmluZ0RmJFBQX3UpCmNsdXN0ZXJpbmdEZiRCcmFrZV91IDwtIE5VTEwKY2x1c3RlcmluZ0RmJEJyYWtlX3N0ZCA8LSBOVUxMCmNsdXN0ZXJpbmdEZiRQUF9iZWZvcmUgPC0gTlVMTApjbHVzdGVyaW5nRGYkUFBfdSA8LSBOVUxMCmNsdXN0ZXJpbmdEZiRQUF9zdGQgPC0gTlVMTAojIGNsdXN0ZXJpbmdEZiRQUF9kZXYgPC0gTlVMTAoKcm93bmFtZXMoY2x1c3RlcmluZ0RmKSA8LSBwYXN0ZTAoIiMiLCBwZXJzb25zKQoKZm9yIChjb2wgaW4gbmFtZXMoY2x1c3RlcmluZ0RmKSkgewogIGNsdXN0ZXJpbmdEZlssY29sXSA8LSBhcy5udW1lcmljKGFzLmNoYXJhY3RlcihjbHVzdGVyaW5nRGZbLCBjb2xdKSkKICAjIGNsdXN0ZXJpbmdEZlssY29sXSA8LSBzY2FsZShjbHVzdGVyaW5nRGZbLGNvbF0pCn0KY2x1c3RlcmluZ0RmCmBgYAoKYGBge3J9CmRmQWN0aXZpdHkgPC0gYWxsX0RyaXZlNFthbGxfRHJpdmU0JFRpbWU9PTYwLF0gJT4lIHNlbGVjdChjKCJTdWJqZWN0IiwgIkFjdGl2aXR5IikpCmRmQWN0aXZpdHkkQWN0aXZpdHlOYW1lIDwtIHNhcHBseShkZkFjdGl2aXR5JEFjdGl2aXR5LCBnZXRBY3Rpdml0eU5hbWUpCmRmQWN0aXZpdHkkU3ViamVjdCA8LSBhcy5mYWN0b3IoZGZBY3Rpdml0eSRTdWJqZWN0KQpyb3duYW1lcyhkZkFjdGl2aXR5KSA8LSBOVUxMCmRmQWN0aXZpdHkgJT4lIHNlbGVjdChjKCJTdWJqZWN0IiwgIkFjdGl2aXR5TmFtZSIpKQpgYGAKCmBgYHtyfQpsaWJyYXJ5KGRlbmRleHRlbmQpCgpOVU1CRVJfT0ZfQ0xVU1RFUlMgPSAzCgpjb2xvcl9kYXJrcGluayA9ICIjZTc1NDgwIgpDTFVTVEVSX0JSQU5DSF9DT0xPUlMgPC0gYygiYmx1ZSIsICJyZWQiLCBjb2xvcl9kYXJrcGluaylbMTpOVU1CRVJfT0ZfQ0xVU1RFUlNdCkNMVVNURVJfTEFCRUxfQ09MT1JTIDwtIGMoImJsdWUiLCAicmVkIiwgY29sb3JfZGFya3BpbmspWzE6TlVNQkVSX09GX0NMVVNURVJTXQoKYmVoYXZpb3JhbE1hdHJpeENsdXN0ZXJpbmcgPC0gYXMubWF0cml4KGNsdXN0ZXJpbmdEZikKcm93bmFtZXMoYmVoYXZpb3JhbE1hdHJpeENsdXN0ZXJpbmcpIDwtIHBhc3RlMChkZkFjdGl2aXR5JEFjdGl2aXR5TmFtZSwgIiAtICMiLCBwZXJzb25zKQpkaXN0TWF0cml4IDwtIGRpc3QoYmVoYXZpb3JhbE1hdHJpeENsdXN0ZXJpbmcsIG1ldGhvZD0ibWFuaGF0dGFuIikKaHJlc3VsdHMgPC0gZGlzdE1hdHJpeCAlPiUgaGNsdXN0CgpoYyA8LSBocmVzdWx0cyAlPiUgCiAgICAgIGFzLmRlbmRyb2dyYW0gJT4lCiAgICAgIHNldCgibm9kZXNfY2V4IiwgTlVNQkVSX09GX0NMVVNURVJTKSAlPiUKICAgICAgc2V0KCJsYWJlbHNfY29sIiwgdmFsdWUgPSBDTFVTVEVSX0xBQkVMX0NPTE9SUywgaz1OVU1CRVJfT0ZfQ0xVU1RFUlMpICU+JQogICAgICAjIHNldCgibGVhdmVzX3BjaCIsIDE5KSAlPiUKICAgICAgIyBzZXQoImxlYXZlc19jb2wiLCB2YWx1ZSA9IGMoImdyYXkiKSwgaz1OVU1CRVJfT0ZfQ0xVU1RFUlMpICU+JSAgICAKICAgICAgc2V0KCJicmFuY2hlc19rX2NvbG9yIiwgdmFsdWU9Q0xVU1RFUl9CUkFOQ0hfQ09MT1JTLCBrPU5VTUJFUl9PRl9DTFVTVEVSUykKCnBsb3QoaGMpCmxlZ2VuZCgidG9wcmlnaHQiLCAKICAgICB0aXRsZT0iRHJpdmU9RmFpbHVyZSBcbkNoYW5nZSBvZiBBcm91c2FsIiwKICAgICBsZWdlbmQgPSBjKCJFeGNlcHRpb25hbCBJbmNyZWFzZSIgLCAiTm90aWNhYmxlIEluY3JlYXNlIiAsICJOby1jaGFuZ2Ugb3IgRGVjcmVhc2UiKSwgCiAgICAgY29sID0gYygicmVkIiwgInBpbmsiICwgImJsdWUiKSwKICAgICBwY2ggPSBjKDIwLDIwLDIwKSwgYnR5ID0gIm4iLCAgcHQuY2V4ID0gMS41LCBjZXggPSAwLjggLCAKICAgICB0ZXh0LmNvbCA9ICJibGFjayIsIGhvcml6ID0gRkFMU0UsIGluc2V0ID0gYygwLjAsIDAuMSkpCmBgYAoKYGBge3J9Ck5VTUJFUl9PRl9DTFVTVEVSUyA9IDIKCmNvbG9yX2RhcmtwaW5rID0gIiNlNzU0ODAiCkNMVVNURVJfQlJBTkNIX0NPTE9SUyA8LSBjKCJibHVlIiwgInJlZCIsIGNvbG9yX2RhcmtwaW5rKVsxOk5VTUJFUl9PRl9DTFVTVEVSU10KQ0xVU1RFUl9MQUJFTF9DT0xPUlMgPC0gYygiYmx1ZSIsICJyZWQiLCBjb2xvcl9kYXJrcGluaylbMTpOVU1CRVJfT0ZfQ0xVU1RFUlNdCgpiZWhhdmlvcmFsTWF0cml4Q2x1c3RlcmluZyA8LSBhcy5tYXRyaXgoY2x1c3RlcmluZ0RmKQpyb3duYW1lcyhiZWhhdmlvcmFsTWF0cml4Q2x1c3RlcmluZykgPC0gcGFzdGUwKGRmQWN0aXZpdHkkQWN0aXZpdHlOYW1lLCAiIC0gIyIsIHBlcnNvbnMpCmRpc3RNYXRyaXggPC0gZGlzdChiZWhhdmlvcmFsTWF0cml4Q2x1c3RlcmluZywgbWV0aG9kPSJtYW5oYXR0YW4iLCBkaWFnID0gVCkKaHJlc3VsdHMgPC0gZGlzdE1hdHJpeCAlPiUgaGNsdXN0KG1ldGhvZD0iYXZlcmFnZSIpCgpoYyA8LSBocmVzdWx0cyAlPiUgCiAgICAgIGFzLmRlbmRyb2dyYW0gJT4lCiAgICAgIHNldCgibm9kZXNfY2V4IiwgTlVNQkVSX09GX0NMVVNURVJTKSAlPiUKICAgICAgc2V0KCJsYWJlbHNfY29sIiwgdmFsdWUgPSBDTFVTVEVSX0xBQkVMX0NPTE9SUywgaz1OVU1CRVJfT0ZfQ0xVU1RFUlMpICU+JQogICAgICAjIHNldCgibGVhdmVzX3BjaCIsIDE5KSAlPiUKICAgICAgIyBzZXQoImxlYXZlc19jb2wiLCB2YWx1ZSA9IGMoImdyYXkiKSwgaz1OVU1CRVJfT0ZfQ0xVU1RFUlMpICU+JSAgICAKICAgICAgc2V0KCJicmFuY2hlc19rX2NvbG9yIiwgdmFsdWU9Q0xVU1RFUl9CUkFOQ0hfQ09MT1JTLCBrPU5VTUJFUl9PRl9DTFVTVEVSUykKCnBsb3QoaGMpCmxlZ2VuZCgidG9wcmlnaHQiLCAKICAgICB0aXRsZT0iRHJpdmU9RmFpbHVyZSBcbkNoYW5nZSBvZiBBcm91c2FsIiwKICAgICBsZWdlbmQgPSBjKCJBY2NlbGVyb3Bob2JpYSIgLCAiTm9ybWFsIiksIAogICAgIGNvbCA9IGMoInJlZCIsICJibHVlIiksCiAgICAgcGNoID0gYygyMCwyMCwyMCksIGJ0eSA9ICJuIiwgIHB0LmNleCA9IDEuNSwgY2V4ID0gMC44ICwgCiAgICAgdGV4dC5jb2wgPSAiYmxhY2siLCBob3JpeiA9IEZBTFNFLCBpbnNldCA9IGMoMC4wLCAwLjEpKQpgYGAKCmBgYHtyfQojIFN0b3JlIGNsdXN0ZXJpbmcgZGF0YQpmUGF0aCA8LSBzdHJfaW50ZXJwKCIuLi9kYXRhL3Byb2Nlc3NlZC9hbmFseXNpcy9UVDFfRHJpdmVfNF9QUC5jc3YiKQpkZnggPC0gY2x1c3RlcmluZ0RmCmRmeCA8LSBjYmluZChwZXJzb25zLCBhcy5udW1lcmljKGJlaGF2aW9yYWxEZiRQUF9iZWZvcmUpLCBhcy5udW1lcmljKGJlaGF2aW9yYWxEZiRQUF91KSwgZGZ4LCBkZkFjdGl2aXR5JEFjdGl2aXR5TmFtZSkKbmFtZXMoZGZ4KSA8LSBjKCJTdWJqZWN0IiwgIlBQX1ByaW9yIiwgIlBQX0FmdGVyIiwgIlBQX0RldiIsICJBY3Rpdml0eSIpCgojIE5vcm1hbGl6ZQpkZnggPC0gZGZ4ICU+JSBtdXRhdGUoUFBfRGV2X05vcm1hbGl6ZWQgPSBpZmVsc2UoUFBfUHJpb3IgPiAwLCBQUF9BZnRlciwgUFBfQWZ0ZXIgLSBQUF9QcmlvcikpCgp3cml0ZS5jc3YoZGZ4LCBmUGF0aCwgcm93Lm5hbWVzID0gRikKYGBgCgpgYGB7cn0KbGlicmFyeShjbHVzdGVyKQpmaXQgPC0ga21lYW5zKGNsdXN0ZXJpbmdEZiwgMikKY2x1c3Bsb3QoY2x1c3RlcmluZ0RmLCBmaXQkY2x1c3RlciwgY29sb3I9VFJVRSwgc2hhZGU9VFJVRSwKICAgbGFiZWxzPTIsIGxpbmVzPTApCmBgYAoKYGBge3J9CnNpbGhvdWV0dGVfc2NvcmUgPC0gZnVuY3Rpb24oayl7CiAga20gPC0ga21lYW5zKGNsdXN0ZXJpbmdEZiwgY2VudGVycyA9IGssIG5zdGFydD0yNSkKICBzcyA8LSBzaWxob3VldHRlKGttJGNsdXN0ZXIsIGRpc3QoY2x1c3RlcmluZ0RmKSkKICBtZWFuKHNzWywgM10pCn0KayA8LSAyOjEwCmF2Z19zaWwgPC0gc2FwcGx5KGssIHNpbGhvdWV0dGVfc2NvcmUpCnBsb3QoaywgdHlwZT0nYicsIGF2Z19zaWwsIHhsYWI9J051bWJlciBvZiBjbHVzdGVycycsIHlsYWI9J0F2ZXJhZ2UgU2lsaG91ZXR0ZSBTY29yZXMnLCBmcmFtZT1GQUxTRSkKYGBgCgoK